package com.wqh.article.command;

import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCollapserKey;
import com.netflix.hystrix.HystrixCollapserProperties;
import com.netflix.hystrix.HystrixCommand;
import com.wqh.article.entity.User;
import com.wqh.article.service.ArticleService;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wanqh
 * @date 2018/01/14 21:14
 * @description: 请求合并器
 */
public class UserCollapdeCommand extends HystrixCollapser<List<User>,User,Long> {
    private ArticleService articleService;
    private Long id;

    public UserCollapdeCommand(ArticleService articleService,Long id){
        //设置时间延迟属性，延迟时间窗为100毫秒
        super(Setter.withCollapserKey(HystrixCollapserKey.Factory.asKey("userCollapdeCommand")).andCollapserPropertiesDefaults(
                HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(100)
        ));
        this.articleService = articleService;
        this.id = id;
    }

    /**
     * 返回单个请求参数id
     * @return
     */
    @Override
    public Long getRequestArgument() {
        return id;
    }

    /**
     * 这里通过获取单个请求的参数来组织批量请求命令UserBatchCommand的实例
     * @param collapsedRequests 保存了延迟时间窗中收集到的所有获取单个User的请求。
     * @return
     */
    @Override
    protected HystrixCommand<List<User>> createCommand(Collection<CollapsedRequest<User, Long>> collapsedRequests) {
        ArrayList<Long> userIds = new ArrayList<>(collapsedRequests.size());
        userIds.addAll(collapsedRequests.stream().map(CollapsedRequest::getArgument).collect(Collectors.toList()));
        return new UserBatchCommand(articleService,userIds);
    }

    /**
     * 该方法在批量请求命令UserBatchCommand执行完成之后执行
     * 通过遍历batchResponse来为collapsedRequests设置请求结果。
     * @param batchResponse 保存了createCommand中组织的批量请求返回结果
     * @param collapsedRequests 每个被合并的请求，
     */
    @Override
    protected void mapResponseToRequests(List<User> batchResponse, Collection<CollapsedRequest<User, Long>> collapsedRequests) {
        int count = 0;
        for (CollapsedRequest<User,Long> collapsedRequest : collapsedRequests){
            User user = batchResponse.get(count++);
            collapsedRequest.setResponse(user);
        }
    }
}
